package org.springblade.common.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.freewayso.image.combiner.ImageCombiner;
import com.freewayso.image.combiner.enums.Direction;
import com.freewayso.image.combiner.enums.OutputFormat;
import com.freewayso.image.combiner.enums.ZoomMode;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseEntity;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tenant.mp.TenantEntity;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.repair.dto.RobotContentDTO;
import org.springblade.modules.repair.dto.RobotMessageDTO;
import org.springblade.modules.repair.dto.RobotPushDTO;
import org.springblade.modules.repair.entity.*;
import org.springblade.modules.repair.entity.Robot;
import org.springblade.modules.repair.enums.MaintainPlanContentEnum;
import org.springblade.modules.repair.enums.RobotStatusEnum;
import org.springblade.modules.repair.service.*;
import org.springblade.modules.repair.utils.HttpHeadUtil;
import org.springblade.modules.repair.vo.GroupRobotConfigVO;
import org.springblade.modules.repair.vo.sign.SignImageWaterMarkVO;
import org.springblade.modules.resource.builder.oss.OssBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Jackey
 * @date 2023年05月17日 16:29
 */
@Slf4j
@Component
public class RobotUtil {

	@Autowired
	IElevatorService elevatorService;
	@Autowired
	ChatGroupService chatGroupService;
	@Autowired
	RobotBuildingElevatorService buildingElevatorService;
	@Autowired
	ChatGroupBuildingService chatGroupBuildingService;
	@Autowired
	RobotService robotService;
	@Autowired
	OssBuilder ossBuilder;
	@Autowired
	GroupRobotConfigService groupRobotConfigService;

	private static final String ROBOT_URL = "https://api-bot.aibotk.com/openapi/v1/chat/room";

	/**
	 * 返回机器人状态 1：正常 0：异常
	 */
	public Boolean getRobotStatus(Long elevatorId) {
		String tenantId = AuthUtil.getTenantId();

		Robot robot = robotService.getOne(new LambdaQueryWrapper<Robot>().eq(TenantEntity::getTenantId, tenantId));
		if (robot == null) {
			throw new ServiceException("未配置机器人信息");
		}

		List<RobotBuildingElevator> buildingElevatorList = buildingElevatorService.list(new LambdaQueryWrapper<RobotBuildingElevator>().eq(RobotBuildingElevator::getElevatorId, elevatorId).eq(TenantEntity::getTenantId, tenantId).eq(BaseEntity::getStatus, 1));
		if (CollectionUtil.isEmpty(buildingElevatorList)) {
			throw new ServiceException("该电梯未绑定机器人");
		}
		List<Long> chatGroupIdList = buildingElevatorList.stream().map(RobotBuildingElevator::getChatgroupId).collect(Collectors.toList());
		List<ChatGroup> chatGroupList = chatGroupService.list(new LambdaQueryWrapper<ChatGroup>().in(ChatGroup::getId, chatGroupIdList).eq(TenantEntity::getTenantId, tenantId));

		//判断电梯是否绑定微信群
		if (CollectionUtil.isEmpty(chatGroupList)) {
			throw new ServiceException("该电梯未绑定机器人");
		}

		for (ChatGroup chatGroup : chatGroupList) {
			//判断群是否绑定正常 && 判断群是否开启机器人消息推送

			if (chatGroup.getStatus().equals(RobotStatusEnum.BINDING_STATUS.BINDING.getValue()) && chatGroup.getPushAllow().equals(RobotStatusEnum.MESSAGE_STATUS.PUSH.getValue())) {
				return Boolean.TRUE;
			}
		}

		return Boolean.FALSE;
	}

	/**
	 * 返回机器人状态 1：正常 0：异常 (仅返回状态 不返回异常)
	 */
	public Boolean getRobotStatusV2(Long elevatorId) {
		String tenantId = AuthUtil.getTenantId();

		Robot robot = robotService.getOne(new LambdaQueryWrapper<Robot>().eq(TenantEntity::getTenantId, tenantId));
		if (robot == null) {
			return Boolean.FALSE;
		}

		List<RobotBuildingElevator> buildingElevatorList = buildingElevatorService.list(new LambdaQueryWrapper<RobotBuildingElevator>().eq(RobotBuildingElevator::getElevatorId, elevatorId).eq(TenantEntity::getTenantId, tenantId).eq(BaseEntity::getStatus, 1));
		if (CollectionUtil.isEmpty(buildingElevatorList)) {
			return Boolean.FALSE;
		}
		List<Long> chatGroupIdList = buildingElevatorList.stream().map(RobotBuildingElevator::getChatgroupId).collect(Collectors.toList());
		List<ChatGroup> chatGroupList = chatGroupService.list(new LambdaQueryWrapper<ChatGroup>().in(ChatGroup::getId, chatGroupIdList).eq(TenantEntity::getTenantId, tenantId));

		//判断电梯是否绑定微信群
		if (CollectionUtil.isEmpty(chatGroupList)) {
			return Boolean.FALSE;
		}

		for (ChatGroup chatGroup : chatGroupList) {
			//判断群是否绑定正常 && 判断群是否开启机器人消息推送

			if (chatGroup.getStatus().equals(RobotStatusEnum.BINDING_STATUS.BINDING.getValue()) && chatGroup.getPushAllow().equals(RobotStatusEnum.MESSAGE_STATUS.PUSH.getValue())) {
				return Boolean.TRUE;
			}
		}

		return Boolean.FALSE;
	}

	/**
	 * 发送机器人文字消息
	 */
	public Boolean sendRobotTextMessage(String tenantId, Long elevatorId, RobotMessageDTO messageDTO) {
		messageDTO.setType(1);
		Robot robot = robotService.getOne(new LambdaQueryWrapper<Robot>().eq(TenantEntity::getTenantId, tenantId));
		if (robot == null) {
			log.warn("未配置机器人信息,租户id: [{}]", tenantId);
			return Boolean.FALSE;
		}

		//获取可以推送的群组
		List<GroupRobotConfigVO> robotConfigs = groupRobotConfigService.getConfigByElevatorId(elevatorId);
		for (GroupRobotConfigVO chatGroup : robotConfigs) {
			List<GroupRobotConfig> msgConfigs = chatGroup.getConfigs();
			long checkSend = msgConfigs.stream().filter(t -> Func.equalsSafe(t.getStatus(), messageDTO.getMaintainType()) && Func.equalsSafe(t.getPushType(), messageDTO.getPushType())).count();
			if (checkSend > 0) {
				RobotPushDTO robotPushDTO = new RobotPushDTO();
				robotPushDTO.setApiKey(robot.getApiKey());
				robotPushDTO.setRoomName(chatGroup.getGroupName());
				robotPushDTO.setMessage(messageDTO);
				System.out.println("Json:" + JSONObject.toJSONString(robotPushDTO));
				HttpUtil.createPost(ROBOT_URL).header("Content-Type", "application/json").body(JSONObject.toJSONString(robotPushDTO)).execute().body();
			}
		}

		return Boolean.TRUE;
	}

	/**
	 * 发送机器人小程序卡片消息
	 */
	public Boolean sendRobotCardMessage(String tenantId, Long elevatorId, RobotMessageDTO messageDTO) {
		boolean result = Boolean.FALSE;
		messageDTO.setType(5);
		Robot robot = robotService.getOne(new LambdaQueryWrapper<Robot>().eq(TenantEntity::getTenantId, tenantId));
		if (robot == null) {
			log.warn("未配置机器人信息,租户id: [{}]", tenantId);
			return result;
		}
		//获取可以推送的群组
		List<GroupRobotConfigVO> robotConfigs = groupRobotConfigService.getConfigByElevatorId(elevatorId);
		for (GroupRobotConfigVO chatGroup : robotConfigs) {
			List<GroupRobotConfig> msgConfigs = chatGroup.getConfigs();
			long checkSend = msgConfigs.stream().filter(t -> Func.equalsSafe(t.getStatus(), messageDTO.getMaintainType()) && Func.equalsSafe(t.getPushType(), messageDTO.getPushType())).count();
			if (checkSend > 0) {
				RobotPushDTO robotPushDTO = new RobotPushDTO();
				robotPushDTO.setApiKey(robot.getApiKey());
				robotPushDTO.setRoomName(chatGroup.getGroupName());
				robotPushDTO.setMessage(messageDTO);
				System.out.println("Json:" + JSONObject.toJSONString(robotPushDTO));
				HttpUtil.createPost(ROBOT_URL).header("Content-Type", "application/json").body(JSONObject.toJSONString(robotPushDTO)).execute().body();
				result = Boolean.TRUE;
			}
		}
		return result;
	}

	/**
	 * 获取电梯对应的微信群组
	 */
	private List<ChatGroup> getChatGroupList(String tenantId, Long elevatorId) {
		List<RobotBuildingElevator> buildingElevatorList = buildingElevatorService.list(new LambdaQueryWrapper<RobotBuildingElevator>().eq(RobotBuildingElevator::getElevatorId, elevatorId).eq(TenantEntity::getTenantId, tenantId).eq(BaseEntity::getStatus, 1));
		if (CollectionUtil.isEmpty(buildingElevatorList)) {
			return null;
		}
		List<Long> chatGroupIdList = buildingElevatorList.stream().map(RobotBuildingElevator::getChatgroupId).collect(Collectors.toList());
		List<ChatGroup> chatGroupList = chatGroupService.list(new LambdaQueryWrapper<ChatGroup>().in(ChatGroup::getId, chatGroupIdList).eq(TenantEntity::getTenantId, tenantId));

		List<ChatGroup> resultChatGroupList = new ArrayList<>();
		for (ChatGroup chatGroup : chatGroupList) {
			//判断群是否绑定正常 && 判断群是否开启机器人消息推送
			if (chatGroup.getStatus().equals(RobotStatusEnum.BINDING_STATUS.BINDING.getValue()) && chatGroup.getPushAllow().equals(RobotStatusEnum.MESSAGE_STATUS.PUSH.getValue())) {
				resultChatGroupList.add(chatGroup);
			}
		}

		return resultChatGroupList;
	}

	public void sendRobotMessage(Long elevatorId, Long planId, RobotContentDTO robotContentDTO) {
		this.sendRobotMessage(RequestContextHolder.getRequestAttributes(), elevatorId, planId, robotContentDTO);
	}

	@Async
	public void sendRobotMessage(RequestAttributes requestAttributes, Long elevatorId, Long planId, RobotContentDTO robotContentDTO) {
		RequestContextHolder.setRequestAttributes(requestAttributes, true);
		this.sendRobotTextMessageByPlan(AuthUtil.getTenantId(), elevatorId, planId, robotContentDTO);
		try {
			if (robotContentDTO.getNotPushCard() != null && robotContentDTO.getNotPushCard()) {
				return;
			}
			this.sendRobotCardMessageByPlan(AuthUtil.getTenantId(),elevatorId, planId, robotContentDTO);
		}catch (Exception e){
			log.error("发送机器人卡片消息失败", e);
		}
	}

	public Boolean sendRobotCardMessage(String tenantId, Long elevatorId, Long planId, RobotContentDTO robotContentDTO) throws Exception {
		return this.sendRobotCardMessageByPlan(tenantId,elevatorId, planId, robotContentDTO);
	}

	private void sendRobotTextMessageByPlan(String tenantId, Long elevatorId, Long planId, RobotContentDTO robotContentDTO) {

		String pagePath = null;
		String content = null;
		//pathUrl填充 content填充
		if (robotContentDTO.getMaintainType().equals(MaintainPlanContentEnum.MAINTAIN_BY.getId())) {
			pagePath = StrUtil.format("ownerPages/elevatorTask/workOrders/detail.html?planId={}&elevatorId={}", planId, elevatorId);

			if ("【开始保养通知】".equals(robotContentDTO.getMaintainSubTypeDesc())) {
				content = StrUtil.format("{}\n{}, 已开始保养, 预计保养时间: {}", robotContentDTO.getMaintainSubTypeDesc(),
					robotContentDTO.getLocationDesc(), robotContentDTO.getMaintainTimeDesc());
			} else if ("【保养到场通知】".equals(robotContentDTO.getMaintainSubTypeDesc())) {
				content = StrUtil.format("{}\n{}, 维保员已到现场, 准备开始保养", robotContentDTO.getMaintainSubTypeDesc(),
					robotContentDTO.getLocationDesc());
			} else if ("【保养退场通知】".equals(robotContentDTO.getMaintainSubTypeDesc())) {
				content = StrUtil.format("{}\n{}, 维保员已退场, 中途暂停保养", robotContentDTO.getMaintainSubTypeDesc(),
					robotContentDTO.getLocationDesc());
			} else {
				content = StrUtil.format("{}\n{}, 已恢复正常运行, 本次保养已完成\n电梯具体保养详情, 可点击小程序查看", robotContentDTO.getMaintainSubTypeDesc(),
					robotContentDTO.getLocationDesc());
			}

		}
		else if(robotContentDTO.getMaintainType().equals(MaintainPlanContentEnum.MAINTAIN_WX.getId())) {
			pagePath = StrUtil.format("packPage/repDetail/repDetail.html?planId={}&elevatorId={}", planId, elevatorId);

			if ("【维修派单通知】".equals(robotContentDTO.getMaintainSubTypeDesc())) {
				content = StrUtil.format("{}\n{}, 报修的电梯故障, 已安排维保员前往处理", robotContentDTO.getMaintainSubTypeDesc(),
					robotContentDTO.getLocationDesc());
			} else if ("【开始维修通知】".equals(robotContentDTO.getMaintainSubTypeDesc())) {
				content = StrUtil.format("{}\n{}, 报修的电梯故障, 已开始维修,预计恢复时间: {}", robotContentDTO.getMaintainSubTypeDesc(),
					robotContentDTO.getLocationDesc(), robotContentDTO.getMaintainTimeDesc());
			} else if ("【维修到场通知】".equals(robotContentDTO.getMaintainSubTypeDesc())) {
				content = StrUtil.format("{}\n{}, 维保员已到现场, 准备开始维修", robotContentDTO.getMaintainSubTypeDesc(),
					robotContentDTO.getLocationDesc());
			} else if ("【维修退场通知】".equals(robotContentDTO.getMaintainSubTypeDesc())) {
				content = StrUtil.format("{}\n{}, 维保员已退场, 中途暂停维修", robotContentDTO.getMaintainSubTypeDesc(),
					robotContentDTO.getLocationDesc());
			} else {
				content = StrUtil.format("{}\n{}, 已恢复正常运行, 本次故障原因是: {}\n电梯具体维修详情, 可点击小程序查看", robotContentDTO.getMaintainSubTypeDesc(),
					robotContentDTO.getLocationDesc(), robotContentDTO.getMalfunctionDesc());
			}
		}
		else if(robotContentDTO.getMaintainType().equals(MaintainPlanContentEnum.MAINTAIN_KR.getId())){
			pagePath = StrUtil.format("ownerPages/elevatorTask/rescue/detail.html?planId={}&elevatorId={}", planId, elevatorId);
			if("【救援调度中】".equals(robotContentDTO.getMaintainSubTypeDesc())){
				content = StrUtil.format("{}\n已接到【{}】的救援申请,工单调度人员中",
					robotContentDTO.getMaintainSubTypeDesc(),
					robotContentDTO.getLocationDesc()
				);
			}
			if("【救援已出发】".equals(robotContentDTO.getMaintainSubTypeDesc())){
				content = StrUtil.format("{}\n{}救援,已安排维保员前往救援,{}",
					robotContentDTO.getMaintainSubTypeDesc(),
					robotContentDTO.getLocationDesc(),
					robotContentDTO.getMalfunctionDesc()
				);
			}
			if("【救援已到达】".equals(robotContentDTO.getMaintainSubTypeDesc())){
				content = StrUtil.format("{}\n{},救援人员-已到达",
					robotContentDTO.getMaintainSubTypeDesc(),
					robotContentDTO.getLocationDesc()
				);
			}
			if("【救援完成】".equals(robotContentDTO.getMaintainSubTypeDesc())){
				content = StrUtil.format("{}\n{}救援,已完成,\n困人原因:{}",
					robotContentDTO.getMaintainSubTypeDesc(),
					robotContentDTO.getLocationDesc(),
					robotContentDTO.getMalfunctionDesc()
				);
			}
		}
		else {
			log.warn("未开发的工单通知类型：{}", robotContentDTO.getMaintainType());
			return;
		}

		RobotMessageDTO robotMessageDTO = new RobotMessageDTO();

		robotMessageDTO.setPagePath(pagePath);
		robotMessageDTO.setContent(content);
		robotMessageDTO.setMaintainType(robotContentDTO.getMaintainType());
		robotMessageDTO.setMaintainSubTypeDesc(robotContentDTO.getMaintainSubTypeDesc());
		this.sendRobotTextMessage(tenantId, elevatorId, robotMessageDTO);
	}


	private Boolean sendRobotCardMessageByPlan(String tenantId, Long elevatorId, Long planId, RobotContentDTO robotContentDTO) throws Exception {

		String pagePath = null;
		String title = null;
		String thumbUrl = null;
		//pathUrl填充 title填充 thumbUrl填充
		if (robotContentDTO.getMaintainType().equals(MaintainPlanContentEnum.MAINTAIN_BY.getId())) {
			pagePath = StrUtil.format("ownerPages/elevatorTask/workOrders/detail.html?planId={}&elevatorId={}", planId, elevatorId);
			title = robotContentDTO.getMaintainSubTypeDesc() + robotContentDTO.getLocationDesc();
			thumbUrl = drawCardImage(robotContentDTO, tenantId);
		}
		else if(robotContentDTO.getMaintainType().equals(MaintainPlanContentEnum.MAINTAIN_WX.getId())) {
			if (robotContentDTO.getMaintainSubTypeDesc().equals("【维修报告通知】")) {
				pagePath = StrUtil.format("packPage/repDetail/reportDetail.html?id={}",planId);
				title = robotContentDTO.getMaintainSubTypeDesc() + robotContentDTO.getLocationDesc();
				thumbUrl = drawCardImage(robotContentDTO, tenantId);
			} else {
				pagePath = StrUtil.format("packPage/repDetail/repDetail.html?planId={}&elevatorId={}", planId, elevatorId);
				title = robotContentDTO.getMaintainSubTypeDesc() + robotContentDTO.getLocationDesc();
				thumbUrl = drawCardImage(robotContentDTO, tenantId);
			}
		}
		else if(new Integer(MaintainPlanContentEnum.MAINTAIN_KR.getId()).equals(robotContentDTO.getMaintainType())){
			pagePath = StrUtil.format("ownerPages/elevatorTask/rescue/detail.html?planId={}&elevatorId={}", planId, elevatorId);
			title = robotContentDTO.getMaintainSubTypeDesc() + robotContentDTO.getLocationDesc();
			thumbUrl = drawCardImage(robotContentDTO, tenantId);
		}
		RobotMessageDTO robotMessageDTO = new RobotMessageDTO();
		robotMessageDTO.setPagePath(pagePath);
		robotMessageDTO.setTitle(title);
		robotMessageDTO.setThumbUrl(thumbUrl);
		robotMessageDTO.setMaintainType(robotContentDTO.getMaintainType());
		robotMessageDTO.setMaintainSubTypeDesc(robotContentDTO.getMaintainSubTypeDesc());
		return this.sendRobotCardMessage(tenantId, elevatorId, robotMessageDTO);
	}

	private String drawCardImage(RobotContentDTO robotContentDTO, String tenantId) throws Exception {
		// 2025-06 适配所需 固定图片路径, 一般不会哈希冲突, 使用Map提高效率
		Map<String, String> imgMap = getImgMap();
		//背景图
		ImageCombiner combiner = new ImageCombiner("https://erised.oss-cn-shenzhen.aliyuncs.com/img/202308240935562.png", OutputFormat.PNG);
		if (robotContentDTO.getMaintainType().equals(MaintainPlanContentEnum.MAINTAIN_BY.getId())) {
			//保养开始通知
			if ("【开始保养通知】".equals(robotContentDTO.getMaintainSubTypeDesc())) {
				//开始保养通知
				return getMaintainPictureUrl(
					robotContentDTO,
					imgMap,
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1749095503243_r1ttz7v4.png",
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1748937018962_7qchsmz4.png",
					true
				);
			}
			else if("【保养到场通知】".equals(robotContentDTO.getMaintainSubTypeDesc())){
				//保养到场通知
				return getMaintainPictureUrl(
					robotContentDTO,
					imgMap,
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1749095532768_g0yetsvw.png",
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1748937018962_7qchsmz4.png",
					true
				);
			}
			else if ("【保养退场通知】".equals(robotContentDTO.getMaintainSubTypeDesc())) {
				return getMaintainPictureUrl(
					robotContentDTO,
					imgMap,
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1749095558903_i44ltclr.png",
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1748937121806_393y664z.png",
					false
				);
			}
			else {
				// 完成
				robotContentDTO.setMaintainImgUrl("https://erised.oss-cn-shenzhen.aliyuncs.com/img/202309041654060.jpg");
				return getMaintainPictureUrl(
					robotContentDTO,
					imgMap,
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1748937303217_6kpc0uqx.png",
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1748937303217_6kpc0uqx.png",
					false
				);
			}
		}
		else if(robotContentDTO.getMaintainType().equals(MaintainPlanContentEnum.MAINTAIN_WX.getId())) {
			if (robotContentDTO.getMaintainSubTypeDesc().equals("【维修派单通知】")) {
				String str1 = "故障描述：";
				String str2 = "维修时间：";
				String str3 = "维修人员：";
				combiner.addTextElement(str1, "/static/yahei.ttc", 24, 20, 29)
					.setLineHeight(33)
					.setColor(153, 153, 153)
					.setDirection(Direction.LeftRight);
				String text = robotContentDTO.getMalfunctionDesc();
				if (StrUtil.length(text) > 13) {
					text = StrUtil.sub(text, 0, 13) + "...";
				}
				combiner.addTextElement(text, "/static/yahei.ttc", Font.BOLD, 24, 140, 29)
					.setLineHeight(33)
					.setColor(51, 51, 51)
					.setDirection(Direction.LeftRight);
				combiner.addTextElement(str2, "/static/yahei.ttc", 24, 20, 74)
					.setLineHeight(33)
					.setColor(153, 153, 153)
					.setDirection(Direction.LeftRight);
				combiner.addTextElement(robotContentDTO.getMaintainTimeDesc(), "/static/yahei.ttc", Font.BOLD, 24, 140, 74)
					.setLineHeight(33)
					.setColor(51, 51, 51)
					.setDirection(Direction.LeftRight);
				combiner.addTextElement(str3, "/static/yahei.ttc", 24, 20, 119)
					.setLineHeight(33)
					.setColor(153, 153, 153)
					.setDirection(Direction.LeftRight);
				List<String> picList = StrUtil.split(robotContentDTO.getMaintainPersonImgDesc(), ",");
				List<String> personList = StrUtil.split(robotContentDTO.getMaintainPersonDesc(), ",");
				if (CollectionUtil.isNotEmpty(picList)) {
					if (picList.size() > 3) {
						picList = picList.subList(0, 3);
					}
					// 计算x轴每个刻度或间隔的长度
					int interval = 500 / (picList.size() + 1);
					for (int j = 0; j < picList.size(); j++) {
						int x = (j + 1) * interval - 72;
						int xText = (j + 1) * interval;
						if (picList.size() == 3) {
							if (j == 0) {
								x -= 25;
								xText -= 25;
							}
							if (j == 2) {
								x += 25;
								xText += 25;
							}
						}
						combiner.addImageElement(picList.get(j), x, 164, 144, 144, ZoomMode.WidthHeight)
							.setRoundCorner(144);
						System.out.println((j + 1) * interval);
						combiner.addTextElement(personList.get(j), "/static/yahei.ttc", Font.BOLD, 24, xText, 320)
							.setLineHeight(33)
							.setAutoFitWidth(90)
							.setColor(51, 51, 51)
							.setDirection(Direction.CenterLeftRight);
					}
				}
			}
			else if (robotContentDTO.getMaintainSubTypeDesc().equals("【开始维修通知】")) {
				return this.getRepairPictureUrl(
					robotContentDTO,
					imgMap,
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1748921375426_y5nc0ler.png",
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1748922800603_6fvhz6p9.png",
					true
					);
			}
			else if (robotContentDTO.getMaintainSubTypeDesc().equals("【维修到场通知】")){
				return this.getRepairPictureUrl(
					robotContentDTO,
					imgMap,
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1748921481271_oydvwqh6.png",
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1748922800603_6fvhz6p9.png",
					true
				);
			}
			else if (robotContentDTO.getMaintainSubTypeDesc().equals("【维修退场通知】")) {
				return this.getRepairPictureUrl(
					robotContentDTO,
					imgMap,
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1749039655591_w9s8cghh.png",
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1748922905083_c3mngd27.png",
					false
				);
			}
			else if (robotContentDTO.getMaintainSubTypeDesc().equals("【维修完成通知】")) {
				robotContentDTO.setMaintainImgUrl("https://erised.oss-cn-shenzhen.aliyuncs.com/img/202309041654060.jpg");
				return this.getRepairPictureUrl(
					robotContentDTO,
					imgMap,
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1748921709961_k4puavbu.png",
					"https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1748921709961_k4puavbu.png",
					true
				);
			}
			else if (robotContentDTO.getMaintainSubTypeDesc().equals("【维修报告通知】")) {
				String str1 = "维修人员：";
				String str2 = "报告时间：";
				combiner.addTextElement(str1, "/static/yahei.ttc", 24, 20, 20)
					.setLineHeight(33)
					.setColor(153, 153, 153)
					.setDirection(Direction.LeftRight);
				combiner.addTextElement(robotContentDTO.getMaintainPersonDesc(), "/static/yahei.ttc", Font.BOLD, 24, 140, 20)
					.setLineHeight(33)
					.setColor(51, 51, 51)
					.setDirection(Direction.LeftRight);
				combiner.addTextElement(str2, "/static/yahei.ttc", 24, 20, 57)
					.setLineHeight(33)
					.setColor(153, 153, 153)
					.setDirection(Direction.LeftRight);
				combiner.addTextElement(robotContentDTO.getMaintainTimeDesc(), "/static/yahei.ttc", Font.BOLD, 24, 140, 57)
					.setLineHeight(33)
					.setColor(51, 51, 51)
					.setDirection(Direction.LeftRight);

				combiner.addImageElement("https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1721789296764_fz9y7yiq.png", 20, 180, 460, 210, ZoomMode.Origin)
					.setRoundCorner(11);
				//设置圆角
				//combiner.addImageElement("https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1721789296764_fz9y7yiq.png", 398, 0, 102, 35, ZoomMode.Origin);
			}
			//执行图片合并
			combiner.combine();
			//可以获取流（并上传oss等）
			InputStream is = combiner.getCombinedImageStream();
			BladeFile bladeFile = ossBuilder.template().putFile(RandomUtil.randomString(10) + ".png", is);
			return bladeFile.getLink();
		}
		else if(robotContentDTO.getMaintainType().equals(MaintainPlanContentEnum.MAINTAIN_KR.getId())){
			if("【救援调度中】".equals(robotContentDTO.getMaintainSubTypeDesc())){
				// 底图
				combiner = new ImageCombiner("https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1723701528745_tq677oe6.jpg",OutputFormat.JPG);
				// 居中蓝字描述
				String middleTitle = "救援人员-调度中";
				combiner.addTextElement(middleTitle, "/static/yahei.ttc", 36, 260, -65)
					.setLineHeight(330)
					.setColor(0, 145, 255)
					.setCenter(true)
					.setDirection(Direction.CenterLeftRight);
			}
			if("【救援已出发】".equals(robotContentDTO.getMaintainSubTypeDesc())){
				// 底图
				combiner = new ImageCombiner("https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1723701600517_zt3ip7ne.jpg", OutputFormat.JPG);
				// 居中蓝字描述
				String middleTitle = "救援人员-已出发";
				combiner.addTextElement(middleTitle, "/static/yahei.ttc", 36, 260, -80)
					.setLineHeight(330)
					.setColor(0, 145, 255)
					.setCenter(true)
					.setDirection(Direction.CenterLeftRight);
				// 居中预计到达时间描述
				String arriveDesc = robotContentDTO.getMalfunctionDesc();
				combiner.addTextElement(arriveDesc, "/static/yahei.ttc", 24, 260, -40)
					.setLineHeight(330)
					.setColor(0, 145, 255)
					.setCenter(true)
					.setDirection(Direction.CenterLeftRight);
				String rescueDesc = "救援人员:";
				combiner.addTextElement(rescueDesc,"/static/yahei.ttc", 36, 200, 85)
					.setLineHeight(250)
					.setColor(0,145,255)
					.setDirection(Direction.RightLeft);
				// 左下角人员头像等
				List<String> picList = StrUtil.split(robotContentDTO.getMaintainPersonImgDesc(), ",");
				List<String> personList = StrUtil.split(robotContentDTO.getMaintainPersonDesc(), ",");
				if (CollectionUtil.isNotEmpty(picList)) {
					if (picList.size() > 3) {
						picList = picList.subList(0, 3);
					}
					int xIndex = 44;
					int xBetween = 118;
					for (int i = 0; i < picList.size(); i++) {
						combiner.addImageElement(picList.get(i),xIndex+xBetween*i,260,62,62,ZoomMode.WidthHeight)
							.setRoundCorner(78);
						if(personList.get(i).length() > 4){
							String s = personList.get(i);
							String substring = s.substring(0, 4);
							substring = substring + "…";
							combiner.addTextElement(substring, "/static/yahei.ttc", Font.BOLD, 18, xIndex+xBetween*i+5, 330);
						}
						else if(personList.get(i).length() < 3){
							combiner.addTextElement(personList.get(i), "/static/yahei.ttc", Font.BOLD, 18, xIndex+xBetween*i+14, 330);
						}
						else {
							combiner.addTextElement(personList.get(i), "/static/yahei.ttc", Font.BOLD, 18, xIndex + xBetween * i + 5, 330);
						}
					}
				}
			}
			if("【救援已到达】".equals(robotContentDTO.getMaintainSubTypeDesc())){
				// 底图
				combiner = new ImageCombiner("https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1723701600517_zt3ip7ne.jpg", OutputFormat.JPG);
				// 居中蓝字描述
				String middleTitle = "救援人员-已到达";
				combiner.addTextElement(middleTitle, "/static/yahei.ttc", 36, 260, -65)
					.setLineHeight(330)
					.setColor(0, 145, 255)
					.setCenter(true)
					.setDirection(Direction.CenterLeftRight);
				String rescueDesc = "救援人员:";
				combiner.addTextElement(rescueDesc,"/static/yahei.ttc", 36, 200, 85)
					.setLineHeight(250)
					.setColor(0,145,255)
					.setDirection(Direction.RightLeft);
				// 左下角人员头像等
				List<String> picList = StrUtil.split(robotContentDTO.getMaintainPersonImgDesc(), ",");
				List<String> personList = StrUtil.split(robotContentDTO.getMaintainPersonDesc(), ",");
				if (CollectionUtil.isNotEmpty(picList)) {
					if (picList.size() > 3) {
						picList = picList.subList(0, 3);
					}
					int xIndex = 44;
					int xBetween = 118;
					for (int i = 0; i < picList.size(); i++) {
						combiner.addImageElement(picList.get(i),xIndex+xBetween*i,260,62,62,ZoomMode.WidthHeight)
							.setRoundCorner(78);
						if(personList.get(i).length() > 4){
							String s = personList.get(i);
							String substring = s.substring(0, 4);
							substring = substring + "…";
							combiner.addTextElement(substring, "/static/yahei.ttc", Font.BOLD, 18, xIndex+xBetween*i+5, 330);
						}
						else if(personList.get(i).length() < 3){
							combiner.addTextElement(personList.get(i), "/static/yahei.ttc", Font.BOLD, 18, xIndex+xBetween*i+14, 330);
						}
						else {
							combiner.addTextElement(personList.get(i), "/static/yahei.ttc", Font.BOLD, 18, xIndex + xBetween * i + 5, 330);
						}
					}
				}
			}
			if("【救援完成】".equals(robotContentDTO.getMaintainSubTypeDesc())){
				// 底图
				combiner = new ImageCombiner("https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1723701649859_99n1w5s7.jpg", OutputFormat.JPG);
				// 居中蓝字描述
				String middleTitle = "救援完成";
				combiner.addTextElement(middleTitle, "/static/yahei.ttc", 36, 225, -65)
					.setLineHeight(330)
					.setColor(85, 163, 2)
					.setDirection(Direction.CenterLeftRight);
				// 右侧对勾
				combiner.addImageElement("https://erised-fresh.oss-cn-shenzhen.aliyuncs.com/592800/1724114695548_h4t1qkhk.png", 305, 79, 48, 48, ZoomMode.Origin);
				String rescueDesc = "救援人员:";
				combiner.addTextElement(rescueDesc,"/static/yahei.ttc", 36, 200, 85)
					.setLineHeight(250)
					.setColor(85, 163, 2)
					.setDirection(Direction.RightLeft);
				// 左下角人员头像等
				List<String> picList = StrUtil.split(robotContentDTO.getMaintainPersonImgDesc(), ",");
				List<String> personList = StrUtil.split(robotContentDTO.getMaintainPersonDesc(), ",");
				if (CollectionUtil.isNotEmpty(picList)) {
					if (picList.size() > 3) {
						picList = picList.subList(0, 3);
					}
					int xIndex = 44;
					int xBetween = 118;
					for (int i = 0; i < picList.size(); i++) {
						combiner.addImageElement(picList.get(i),xIndex+xBetween*i,260,62,62,ZoomMode.WidthHeight)
							.setRoundCorner(78);
						if(personList.get(i).length() > 4){
							String s = personList.get(i);
							String substring = s.substring(0, 4);
							substring = substring + "…";
							combiner.addTextElement(substring, "/static/yahei.ttc", Font.BOLD, 18, xIndex+xBetween*i+5, 330);
						}
						else if(personList.get(i).length() < 3){
							combiner.addTextElement(personList.get(i), "/static/yahei.ttc", Font.BOLD, 18, xIndex+xBetween*i+14, 330);
						}
						else{
							combiner.addTextElement(personList.get(i), "/static/yahei.ttc", Font.BOLD, 18, xIndex+xBetween*i+5, 330);
						}
					}
				}
			}
			//执行图片合并
			combiner.combine();
			//可以获取流（并上传oss等）
			InputStream is = combiner.getCombinedImageStream();
			BladeFile bladeFile = ossBuilder.template().putFile(RandomUtil.randomString(10) + ".png", is);
			return bladeFile.getLink();
		}
		else {
			log.warn("未开发的工单通知类型");
		}
		return null;
	}

	/**
	 * 2025-06
	 * 当没有水印图片时，默认右侧图片，用于做默认值判断
	 * @return 图片urlMap
	 */
	private Map<String, String> getImgMap() {
		Map<String, String> imgMap = new HashMap<>(20);
		// 对象图片路径默认值
		imgMap.put("https://erised.oss-cn-shenzhen.aliyuncs.com/img/202309041654060.jpg", "对象默认值");
		imgMap.put("https://erised.oss-cn-shenzhen.aliyuncs.com/img/202308251732973.png", "开始维修，保养开始及保养到场通知默认图片");
		imgMap.put("https://erised.oss-cn-shenzhen.aliyuncs.com/img/202308251731106.png", "维修到场通知默认图片");
		imgMap.put("https://erised.oss-cn-shenzhen.aliyuncs.com/img/202308251732342.png", "维修和保养退场通知默认图片");
		return imgMap;
	}


	private BufferedImage convertImg(String url) throws MalformedURLException {
		//源图片
		BufferedImage sourceImage = ImgUtil.read(new URL(url));
		int sourceHeight = sourceImage.getHeight();
		int sourceWidth = sourceImage.getWidth();
		float scale = 460 / (float) sourceWidth;

		//缩放原图
		Image scaleImage = ImgUtil.scale(
			sourceImage,
			scale
		);
		int scaleWidth = scaleImage.getWidth(null);
		int scaleHeight = scaleImage.getHeight(null);

		//获取原图锚点
		int x = (sourceWidth - scaleWidth) / 2;
		int y = (sourceHeight - scaleHeight + (scaleHeight - 210)) / 2;

		//裁切原图
		Image cutImage = ImgUtil.cut(sourceImage, new Rectangle(x, y, scaleWidth, 210));
		return ImgUtil.toBufferedImage(cutImage);
	}

	/**
	 * 较长文本分两行处理
	 * @param content 文本
	 * @return 处理后的结果
	 */
	private Map<String,String> cutIntoTwoLines(String content){
		Map<String,String> result = new HashMap<>();
		if(Func.isBlank(content)){
			result.put("firstLine", "");
			result.put("secondLine", "");
			return result;
		}
		int lengthLimit = 9;
		String firstLine;
		String secondLine = "";
		if(content.length() > lengthLimit){
			// 截取9个字符之后作为第二行，若第二行依然超过限制，截取前8个字符作为第二行并拼接...
			secondLine = StrUtil.sub(content, lengthLimit, content.length());
			if(secondLine.length() > lengthLimit){
				secondLine = StrUtil.sub(secondLine, 0, lengthLimit-1) + "...";
			}
			// 截取前9个字符作为第一行
			firstLine = StrUtil.sub(content, 0, lengthLimit);
		}else{
			firstLine = content;
		}
		result.put("firstLine", firstLine);
		result.put("secondLine", secondLine);
		return result;
	}

	/**
	 * 根据指定长度文本截取处理
	 * @param content 文本
	 * @param lengthLimit 长度限制
	 * @return 处理后的结果
	 */
	private String cutLineByLength(String content, int lengthLimit){
		if(Func.isBlank(content)){
			return "";
		}
		if(content.length() > lengthLimit){
			content = StrUtil.sub(content, 0, lengthLimit-1) + "...";
		}
		return content;
	}

	/**
	 * 组装水印图片
	 */
	private String makeWaterMarkPicture(String pictureUrl){
		// 使用head请求pictureUrl，并获取响应头中的 x-oss-meta-watermark String 值
		try {
			String decodedWatermark = HttpHeadUtil.getDecodedWatermark(pictureUrl);
			if(Func.isNotBlank(decodedWatermark)){
				//  画图
				SignImageWaterMarkVO signImageWaterMarkVO = JSON.parseObject(decodedWatermark, SignImageWaterMarkVO.class);
				// 指定宽高创建combiner
				ImageCombiner waterMarkCombiner = new ImageCombiner(pictureUrl,230,294,ZoomMode.WidthHeight, OutputFormat.PNG);
				//  获取时间：分秒
				// yyyy-MM-dd HH:mm:ss
				String createTime = signImageWaterMarkVO.getCreateTime();
				// 转换成Date对象
				DateTime parseDate = DateUtil.parse(createTime, "yyyy-MM-dd HH:mm:ss");
				// 获取 年-月-日
				String dateStr = DateUtil.format(parseDate, "yyyy-MM-dd");
				waterMarkCombiner.addTextElement(dateStr, "/static/yahei.ttc", Font.BOLD, 11, 98, 230)
					.setColor(255,255,255);
				// 获取 时：分
				String timeStr = DateUtil.format(parseDate, "HH:mm");
				waterMarkCombiner.addTextElement(timeStr, "/static/yahei.ttc", Font.BOLD, 30, 6, 206)
					.setColor(255,255,255);
				// 获取 周几
				String weekStr = DateUtil.format(parseDate, "E");
				waterMarkCombiner.addTextElement(weekStr, "/static/yahei.ttc", Font.BOLD, 11, 98, 215)
					.setColor(255,255,255);
				// 水平线，用删除线代替
				waterMarkCombiner.addTextElement("                                                      ", "/static/yahei.ttc", Font.BOLD, 11, 6, 240)
					.setColor(255,255,255)
					.setStrikeThrough(true);
				// 项目
				String buildingName = signImageWaterMarkVO.getBuildingName();
				buildingName = this.cutLineByLength(buildingName,16);
				waterMarkCombiner.addTextElement("项目： " + buildingName, "/static/yahei.ttc", Font.BOLD, 10, 6, 252)
					.setColor(255,255,255);
				// 梯号
				String elevatorAddress = signImageWaterMarkVO.getElevatorName();
				waterMarkCombiner.addTextElement("梯号： " + elevatorAddress, "/static/yahei.ttc", Font.BOLD, 10, 6, 267)
					.setColor(255,255,255);
				// 定位
				String location = signImageWaterMarkVO.getAddress();
				location = this.cutLineByLength(location,16);
				waterMarkCombiner.addTextElement("定位： " + location, "/static/yahei.ttc", Font.BOLD, 10, 6, 280)
					.setColor(255,255,255);
				waterMarkCombiner.combine();
				InputStream is = waterMarkCombiner.getCombinedImageStream();
				BladeFile bladeFile = ossBuilder.template().putFile(RandomUtil.randomString(10) + ".png", is);
				return bladeFile.getLink();
			}
		} catch (Exception e) {
			log.error("获取水印图片失败", e);
			return null;
		}
		return null;
	}

	/**
	 * 2025-06 抽出维修业务相关，除了预计恢复时间均为公共数据
	 * 维修业务相关 图片处理
	 * @return OSS链接
	 */
	private String getRepairPictureUrl(
		RobotContentDTO robotContentDTO,
		Map<String, String> imgMap,
		String defaultImgUrlWithOutWaterMark,
		String defaultImgUrlForWaterMark,
		Boolean needRecoveryTime
	) throws Exception {
		// 2025-06-03 样式调整，替换为不同格式的底图，不复用combiner，使用当前块的repairSendCombiner
		// 定义底图，适配旧代码，当目前右侧目标图片为默认图片时，使用默认底图，否则使用自定义底图
		ImageCombiner repairSendCombiner = new ImageCombiner(defaultImgUrlForWaterMark, OutputFormat.PNG);
		// 右侧原图路径
		String maintainImgUrl = robotContentDTO.getMaintainImgUrl();
		// 维修派单的情况，当前maintainImgUrl有可能是默认值，当为默认值时，使用默认底图，当不为默认值时，使用maintainImgUrl并进行水印处理
		if (!imgMap.containsKey(maintainImgUrl)) {
			// 处理水印图片，返回图片url
			String waterMarkPictureUrl = this.makeWaterMarkPicture(maintainImgUrl);
			if (Func.isNotBlank(waterMarkPictureUrl)) {
				repairSendCombiner.addImageElement(waterMarkPictureUrl, 230, 53, 230, 294, ZoomMode.WidthHeight)
					.setRoundCorner(15);
			}
		} else {
			// 使用默认底图
			repairSendCombiner = new ImageCombiner(defaultImgUrlWithOutWaterMark, OutputFormat.PNG);
		}
		// 获取插入文字原文、处理
		// 电梯状态
		String elevatorStatus = robotContentDTO.getElevatorStatusDesc();
		// 故障描述原文
		String faultReasonContent = robotContentDTO.getMalfunctionDesc();
		// 维修人员
		String repairPerson = robotContentDTO.getMaintainPersonDesc();
		// 处理文字
		elevatorStatus = this.cutLineByLength(elevatorStatus,9);
		Map<String, String> faultReasonMap = this.cutIntoTwoLines(faultReasonContent);
		String firstLine = faultReasonMap.get("firstLine");
		String secondLine = faultReasonMap.get("secondLine");
		repairPerson = this.cutLineByLength(repairPerson,9);
		repairSendCombiner.addTextElement(elevatorStatus, "/static/yahei.ttc", Font.BOLD, 24, 14, 80)
			.setColor(51, 51, 51);
		repairSendCombiner.addTextElement(firstLine, "/static/yahei.ttc", Font.BOLD, 24, 14, 158)
			.setColor(51, 51, 51);
		if (Func.isNotBlank(secondLine)) {
			repairSendCombiner.addTextElement(secondLine, "/static/yahei.ttc", Font.BOLD, 24, 14, 182)
				.setColor(51, 51, 51);
		}
		repairSendCombiner.addTextElement(repairPerson, "/static/yahei.ttc", Font.BOLD, 24, 14, 270)
			.setColor(51, 51, 51);
		if (needRecoveryTime) {
			// 预计恢复时间
			String recoveryTime = robotContentDTO.getMaintainTimeDesc();
			recoveryTime = this.cutLineByLength(recoveryTime,30);
			repairSendCombiner.addTextElement(recoveryTime, "/static/yahei.ttc", Font.BOLD, 24, 14, 348)
				.setColor(51, 51, 51);
		}
		//执行图片合并
		repairSendCombiner.combine();
		//可以获取流（并上传oss等）
		InputStream is = repairSendCombiner.getCombinedImageStream();
		BladeFile bladeFile = ossBuilder.template().putFile(RandomUtil.randomString(10) + ".png", is);
		return bladeFile.getLink();
	}

	/**
	 * 2025-06 抽出维修业务相关，除了预计恢复时间均为公共数据
	 * 维修业务相关 图片处理
	 * @return OSS链接
	 */
	private String getMaintainPictureUrl(
		RobotContentDTO robotContentDTO,
		Map<String, String> imgMap,
		String defaultImgUrlWithOutWaterMark,
		String defaultImgUrlForWaterMark,
		Boolean needRecoveryTime
	) throws Exception {
		// 2025-06-03 样式调整，替换为不同格式的底图，不复用combiner，使用当前块的repairSendCombiner
		// 定义底图，适配旧代码，当目前右侧目标图片为默认图片时，使用默认底图，否则使用自定义底图
		ImageCombiner maintainSendCombiner = new ImageCombiner(defaultImgUrlForWaterMark, OutputFormat.PNG);
		// 右侧原图路径
		String maintainImgUrl = robotContentDTO.getMaintainImgUrl();
		// 维修派单的情况，当前maintainImgUrl有可能是默认值，当为默认值时，使用默认底图，当不为默认值时，使用maintainImgUrl并进行水印处理
		if (!imgMap.containsKey(maintainImgUrl)) {
			// 处理水印图片，返回图片url
			String waterMarkPictureUrl = this.makeWaterMarkPicture(maintainImgUrl);
			if (Func.isNotBlank(waterMarkPictureUrl)) {
				maintainSendCombiner.addImageElement(waterMarkPictureUrl, 230, 53, 230, 294, ZoomMode.WidthHeight)
					.setRoundCorner(15);
			}
		} else {
			// 使用默认底图
			maintainSendCombiner = new ImageCombiner(defaultImgUrlWithOutWaterMark, OutputFormat.PNG);
		}
		// 获取插入文字原文、处理
		// 电梯状态
		String elevatorStatus = robotContentDTO.getElevatorStatusDesc();
		// 保养人员
		String maintainPerson = robotContentDTO.getMaintainPersonDesc();
		// 处理文字
		elevatorStatus = this.cutLineByLength(elevatorStatus,9);
		maintainPerson = this.cutLineByLength(maintainPerson,9);
		maintainSendCombiner.addTextElement(elevatorStatus, "/static/yahei.ttc", Font.BOLD, 24, 14, 80)
			.setColor(51, 51, 51);
		maintainSendCombiner.addTextElement(maintainPerson, "/static/yahei.ttc", Font.BOLD, 24, 14, 158)
			.setColor(51, 51, 51);
		if (needRecoveryTime) {
			// 预计保养时间
			String recoveryTime = robotContentDTO.getMaintainTimeDesc();
			recoveryTime = this.cutLineByLength(recoveryTime,13);
			maintainSendCombiner.addTextElement(recoveryTime, "/static/yahei.ttc", Font.BOLD, 24, 14, 236)
				.setColor(51, 51, 51);
		}
		//执行图片合并
		maintainSendCombiner.combine();
		//可以获取流（并上传oss等）
		InputStream is = maintainSendCombiner.getCombinedImageStream();
		BladeFile bladeFile = ossBuilder.template().putFile(RandomUtil.randomString(10) + ".png", is);
		return bladeFile.getLink();
	}
}
